/**
 * @author James Crockford
 * See http://javascript.crockford.com/inheritance.html
 */

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Function.method('inherits', function (parent) {
    var d = {}, p = (this.prototype = new parent());
    this.method('uber', function uber(name) {
        if (!(name in d)) {
            d[name] = 0;
        }        
        var f, r, t = d[name], v = parent.prototype;
        if (t) {
            while (t) {
                v = v.constructor.prototype;
                t -= 1;
            }
            f = v[name];
        } else {
            f = p[name];
            if (f == this[name]) {
                f = v[name];
            }
        }
        d[name] += 1;
        r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
        d[name] -= 1;
        return r;
    });
    return this;
});

Function.method('swiss', function (parent) {
    for (var i = 1; i < arguments.length; i += 1) {
        var name = arguments[i];
        this.prototype[name] = parent.prototype[name];
    }
    return this;
});

Function.method('include', function (parent) {
    for each (var method in parent) {
        this.prototype[method.StName()] = parent[method];
    }
    return this;
});

Function.prototype.DeriveFrom = function (fnSuper) {
    var prop;
    if (this == fnSuper) {
        alert("Error - cannot derive from self");
        return;
    }
    for (prop in fnSuper.prototype) {
        if (typeof fnSuper.prototype[prop] == "function" &&
            !this.prototype[prop]) {
            this.prototype[prop] = fnSuper.prototype[prop];
        }
    }
    this.prototype[fnSuper.StName()] = fnSuper;
}
Function.prototype.StName = function () {
    var st;
    st = this.toString();
    st = st.substring(st.indexOf(" ") + 1, st.indexOf("("));
    if (st.charAt(0) == "(") {
        st = "function ...";
    }
    return st;
}
Function.prototype.Override = function (fnSuper, stMethod) {
    this.prototype[fnSuper.StName() + "_" + stMethod] = fnSuper.prototype[stMethod];
}

// Prototypical inheritance

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

